/**
 * @file trayinfo.h
 * Main definitions for TrayInfo.
 */

/* Created by Laszlo Ashin <kodest@gmail.com> */

#ifndef _TRAYINFO_H
#define _TRAYINFO_H	1

#include <sys/time.h>
#include <sys/types.h>

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */

/** 
 * Location of the configuration file under the current user's home directory.
 */
#define CONFIG_FNAME	"/.config/trayinfo"

/** Seconds to wait before a reconnect attempt. */
#define WAIT_RETRY	30

/** Maximal length of a source name. */
#define SOURCE_NAME_SIZE	16

/** Maximal length of a module name. */
#define MODULE_NAME_SIZE	16

/** Maximal length of a config item name. */
#define CONFIG_ITEM_NAME_SIZE	32

/** Make trayinfo to quit after the next main loop iteration. */
void request_quit(void); 

/** Prototype for a configuration option handler callback function. */
typedef int (*config_handler_t)(const char *s);

/**
 * Registers a new configuration option handler.
 * @param name Name of the configuration option.
 * @param handler Function pointer of the handler.
 * @return Zero on success.
 */
int register_config_handler(/*@dependent@*/ const char *name,
	config_handler_t handler);

/**
 * Removes a registered configuration option handler.
 * @param name Name of the configuration option.
 * @param handler Function pointer of the handler.
 * @return Zero on success.
 */
int forget_config_handler(const char *name, config_handler_t handler);

/** Handle of a source. */
typedef void source_handle_t;

/** Structure containing the definition of a source. */
typedef struct source_s {

	/** Short unique name of the source. */
	const char name[SOURCE_NAME_SIZE];

	/**
	 * Initialization function of the source.
	 * @param sh Source handle.
	 * @return Zero on success.
	 */
	int (*init)(source_handle_t *sh);

	/** Finalization function of the source. */
	void (*done)(void);

	/**
	 * Gets called if the source may print something.
	 * @param now Current time when calling.
	 * @param fd Current file descriptor.
	 * @return Number of characters printed.
	 * @see fd
	 */
	int (*write)(double now, int fd);

	/**
	 * If the source has defined a network connection, trayinfo will
	 * keep trying to open that connection in case of it has not been
	 * already opened.
	 * @return File descriptor of the opened stream or negative on error.
	 */
	int (*open)(void);

	/**
	 * If read() returns error or zero length then trayinfo closes
	 * the connection associated with this source. A retry will happen.
	 * @param fd File descriptor of the socked to close.
	 * @see last_retry
	 * @see wait_retry
	 */
	void (*close)(int fd);

	/**
	 * Gets called if there is available data if the already opened
	 * socket associated with this source.
	 * @param fd File descriptor of socket to read from.
	 * @return Number of bytes read, negative on error or zero on EOF.
	 */
	ssize_t (*read)(int fd);

	/** Seconds to wait till the next open() attempt. */
	int wait_retry;

} source_t;

/**
 * Sends data through sendq.
 * @param sh Handle of the source which attempts to send data.
 * @param buf Buffer filled up with data we trying to send.
 * @param len Number of bytes we desire to send.
 * @return Number of bytes successfuly sent or -1 on error.
 */
ssize_t source_send(source_handle_t *sh, const void *buf, size_t len);

/**
 * Registers a new data source.
 * @param source An initialized structure of data source.
 * @return Handle of the new source or NULL.
 */
source_handle_t *register_source(source_t *source);

/**
 * Removes a registered data source.
 * @param sh Handle of the source to forget.
 * @return Zero on success.
 */
int forget_source(source_handle_t *sh);

/** Possible phases of a module's life cycle. */
typedef enum {

	/** The module has just born. */
	MODULE_PHASE_INIT,

	/** The module will be terminated soon. */
	MODULE_PHASE_EXIT

} module_phase_t;

/** Prototype for modules init functions. */
typedef int (*module_init_func_t)(module_phase_t module_phase);

#endif /* _TRAYINFO_H */
